import base64
import sys
from datetime import datetime
from io import BytesIO
from PIL import Image, ImageFont, ImageDraw   #他改名字了 Pillow
from flask import make_response, session, url_for
import random
import string
from models import DCategory
import bcrypt
#获取分类名称
def get_cate_name(id):

    info= DCategory.query.filter(DCategory.id == id).first()
    return info.name
#自定义函数
def haha(s):
    return s+'haha!'
#验证可上传文件类型
def allowed_file(filename,ALLOWED_EXTENSIONS):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#验证码类
class imageCode():
    '''
    验证码处理
    '''
    def rndColor(self):
        '''随机颜色'''
        return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
    def geneText(self):
        '''生成4位验证码'''
        return ''.join(random.sample(string.ascii_letters + string.digits, 4)) #ascii_letters是生成所有字母 digits是生成所有数字0-9
    def drawLines(self, draw, num, width, height):
        '''划线'''
        for num in range(num):
            x1 = random.randint(0, width / 2)
            y1 = random.randint(0, height / 2)
            x2 = random.randint(0, width)
            y2 = random.randint(height / 2, height)
            draw.line(((x1, y1), (x2, y2)), fill='black', width=1)
    def getVerifyCode(self):
        '''生成验证码图形'''
        code = self.geneText()
        # 图片大小120×50
        width, height = 120, 50
        # 新图片对象
        im = Image.new('RGB', (width, height), 'white')
        # 字体
        font = ImageFont.truetype('./static/Arial.ttf', 40)
        # draw对象
        draw = ImageDraw.Draw(im)
        # 绘制字符串
        for item in range(4):
            draw.text((5 + random.randint(-3, 3) + 23 * item, 5 + random.randint(-3, 3)),
                      text=code[item], fill=self.rndColor(), font=font)
        # 划线
        self.drawLines(draw, 2, width, height)
        return im, code
    def getImgCode(self):
        image, code = self.getVerifyCode()
        # 图片以二进制形式写入
        buf = BytesIO()
        image.save(buf, 'jpeg')
        buf_str = buf.getvalue()
        # 把buf_str作为response返回前端，并设置首部字段
        response = make_response(buf_str)
        response.headers['Content-Type'] = 'image/gif'
        # 将验证码字符串储存在session中
        session['vercode'] = code
        print('当前验证码'+code)
        return response

#获取自定义函数列表
def get_custom_functions():
    import inspect
    # 获取当前模块的名字
    current_module_name = sys.modules[__name__].__name__

    # 获取当前模块
    current_module = sys.modules[current_module_name]

    """获取模块中的自定义函数列表"""
    custom_functions = []
    for name, obj in inspect.getmembers(current_module):
        if inspect.isfunction(obj) and getattr(obj, '__module__', None) == current_module.__name__:
            custom_functions.append(name)
    return custom_functions

#字典转url参数字符串
def dict_to_query_string(data_dict):
    # 使用字典推导式将字典项转换为'key=value'格式的字符串
    items = ['{}={}'.format(key, value) for key, value in data_dict.items()]
    # 使用'&'连接所有的'key=value'字符串
    query_string = '&'.join(items)
    return query_string

#模型转字典
# def model_to_dict(model):
#     return {col: value for col, value in vars(model).items()}
def model_to_dict(model):
    """
    将 SQLAlchemy 模型对象转换为字典。
    :param model: SQLAlchemy 模型对象
    :return: 包含模型字段和值的字典
    """
    # 使用模型的 __tablename__ 属性来获取表名（可选，用于调试或日志记录）
    # table_name = model.__tablename__
    # 初始化一个空字典来存储字段和值
    model_dict = {}
    # 遍历模型对象的所有属性
    for column in model.__mapper__.columns:
        # 获取属性名（即列名）
        column_name = column.key

        # 获取属性值
        column_value = getattr(model, column_name, None)
        if isinstance(column_value, datetime):
            # 对日期字段进行格式化
            model_dict[column_name] = column_value.strftime("%Y-%m-%d %H:%M:%S")
        else:
            # 将字段名和值添加到字典中
            model_dict[column_name] = column_value
    # 返回包含模型字段和值的字典
    return model_dict

#将一组数据转为list
def list_to_json(object):
    return [model_to_dict(c) for c in object]

#随即产生字符串
def generate_random_filename(length):
    # 生成指定长度的随机文件名
    filename = ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
    return filename

#自定义生成URL
def get_url(endpoint,params=None):
    try:
        return url_for(endpoint) if params==None else url_for(endpoint,**params)
    except RuntimeError:
        return None  # 或者你可以返回一个默认的URL

# 哈希密码
def hash_password(password: str) -> str:
    """
    哈希密码并返回哈希值的Base64编码字符串。
    :param password: 明文密码
    :return: Base64编码的哈希密码字符串
    """
    # 生成盐值并哈希密码
    salt = bcrypt.gensalt()
    hashed = bcrypt.hashpw(password.encode('utf-8'), salt)

    # 将哈希值的字节串转换为Base64编码的字符串
    hashed_str = base64.b64encode(hashed).decode('utf-8')
    return hashed_str

#验证密码
def verify_password(stored_password_str: str, provided_password: str) -> bool:
    """
    验证提供的密码是否与存储的Base64编码的哈希密码匹配。

    :param stored_password_str: 存储的Base64编码的哈希密码字符串
    :param provided_password: 用户提供的明文密码
    :return: 密码是否匹配
    """
    # 将存储的Base64编码的哈希密码字符串解码为字节串
    stored_password_bytes = base64.b64decode(stored_password_str)

    # 检查提供的密码是否与存储的哈希密码匹配
    return bcrypt.checkpw(provided_password.encode('utf-8'), stored_password_bytes)

